﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FluentNHibernate.Cfg;
using NHibernate.Cfg;
using NHibernate.Cfg.Loquacious;
using NHibernate.Tool.hbm2ddl;
using FluentNHibernate.Automapping;
using NHibernate;
using FluentNHibernate.Cfg.Db;
using Mecanica.Repositório.Convencoes;

namespace Mecanica.Repositório.Configuracao
{
    public class SessionNHibernateModule
    {
        public string ConnectionString { get; set; }

       // public Assembly AssemblyMapper { get; set; }

        public ISessionFactory FabricaSessao { get; set; }

        public SessionNHibernateModule()
        {        
            var cfg = BuildConfiguration();

            var persistenceModel = BuildPersistenceModel();
            //persistenceModel.Configure(cfg);

            var convencoes = new MapeamentoConfiguracao();

            var mapeamento = AutoMap.AssemblyOf<Dominio.Entidades.Core.Usuario>(convencoes);
            mapeamento.Conventions.Add<TableNameConvention>();
            mapeamento.Conventions.Add<PrimaryKeyNameConvention>();

            var cfgFluent = FluentNHibernate.Cfg.Fluently.Configure(cfg).Mappings(x =>
                  x.AutoMappings.Add(mapeamento));

            cfg = cfgFluent.BuildConfiguration();

            this.FabricaSessao = BuildSessionFactory(cfg);

            BuildSchema(cfg);
            //RegisterConponents(cfg, sessionFactory);
        }

        public Configuration BuildConfiguration()
        {
            NHibernate.Cfg.Configuration configuracao = new NHibernate.Cfg.Configuration();
            configuracao.DataBaseIntegration(x =>
            {
                x.ConnectionStringName = "conexaoPostgres";
                x.Dialect<NHibernate.Dialect.PostgreSQL82Dialect>();
                x.Driver<NHibernate.Driver.NpgsqlDriver>();
                x.LogFormatedSql = true;
                x.LogSqlInConsole = true;
            })
            .Proxy(x=>x.ProxyFactoryFactory<NHibernate.ByteCode.Castle.ProxyFactoryFactory>());
                        
             return configuracao;
        }

        public AutoPersistenceModel BuildPersistenceModel()
        {
            var persistenceModel = new AutoPersistenceModel();

            persistenceModel.ValidationEnabled = true;
            persistenceModel.Conventions.Setup(c =>
            {
            //    //c.Add(typeof(ForeignKeyNameConvention));
            //    //c.Add(typeof(ReferenceConvention));
            //    //c.Add(typeof(PrimaryKeyNameConvention));
               c.Add(typeof(TableNameConvention));
            });

            persistenceModel.AddMappingsFromAssembly(typeof(Dominio.Entidades.Core.Usuario).Assembly);
            
            persistenceModel.WriteMappingsTo(@"./");

            return persistenceModel;
        }

        public ISessionFactory BuildSessionFactory(Configuration config)
        {
            var sessionFactory = config.BuildSessionFactory();

            if (sessionFactory == null)
                throw new Exception("Cannot build NHibernate Session Factory");

            return sessionFactory;
        }

        //public void RegisterConponents(Configuration config, ISessionFactory sessionFactory)
        //{
        //    builder.RegisterInstance(config).As<Configuration>().SingleInstance();
        //    builder.RegisterInstance(sessionFactory).As<ISessionFactory>().SingleInstance();
        //    builder.Register(x => x.Resolve<ISessionFactory>().OpenSession()).As<ISession>().InstancePerLifetimeScope();
        //    builder.Register(x => new UnitOfWork(x.Resolve<ISessionFactory>())).As<IUnitOfWork>();
        //    builder.Register(x => new UnitOfWorkFactory()).As<IUnitOfWorkFactory>().SingleInstance();
        //}

        private static void BuildSchema(Configuration config)
        {
            new SchemaExport(config).SetOutputFile(@"./Schema.sql").Create(true, true);
            new SchemaExport(config).Execute(true, true, false);
        }
    }
}
